﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

namespace WSocks5Server
{
    public partial class MainForm : Form
    {
        private bool Exit;
        private System.Timers.Timer timer = null;
        private string Port = ConfigurationManager.AppSettings["Port"].ToString();
        private string Second = ConfigurationManager.AppSettings["Second"].ToString();

        public MainForm()
        {
            InitializeComponent();
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x11)
            {
                this.Exit = true;
            }
            base.WndProc(ref m);
        }

        /// <summary>
        /// 写入日志
        /// </summary>
        /// <param name="msg"></param>
        private void WriteLog(string msg)
        {
            Action act = delegate ()
            {
                if (txtLog.Text.Length > 10000)
                {
                    ClearLog();
                }
                txtLog.Text += msg + Environment.NewLine;
                ScrollLog();
            };
            Invoke(act);
        }

        /// <summary>
        /// 清除日志
        /// </summary>
        private void ClearLog()
        {
            Action act = delegate ()
            {
                txtLog.Text = string.Empty;
            };
            Invoke(act);
        }

        /// <summary>
        /// 滚动日志
        /// </summary>
        private void ScrollLog()
        {
            Action act = delegate ()
            {
                txtLog.SelectionStart = txtLog.Text.Length;
                txtLog.ScrollToCaret();
            };
            Invoke(act);
        }

        /// <summary>
        /// 执行事件
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void Event(object source, System.Timers.ElapsedEventArgs e)
        {
            Action act = delegate ()
            {
                WriteLog("执行事件......");
                if ("启动服务".Equals(btnStartServer.Text)) { 
                    btnStartServer_Click(null, null);
                }
            };
            Invoke(act); 
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            new Thread(() => {
                WriteLog(Environment.NewLine + "窗体加载......");
            }).Start();
            try
            {
                nudPort.Value = Decimal.Parse(Port);
            }
            catch
            {
                nudPort.Value = 1080;
            }
            try
            {
                int DefaultTime = Convert.ToInt32(Second) * 1000;
                timer = new System.Timers.Timer(DefaultTime); //实例化Timer类，设置间隔时间为10000毫秒； 
                timer.Elapsed += new System.Timers.ElapsedEventHandler(Event); //到达时间的时候执行事件； 
                timer.AutoReset = true;//设置是执行一次（false）还是一直执行(true)； 
                timer.Enabled = true;//是否执行System.Timers.Elapsed事件； 
                timer.Start();
            }
            catch
            {
                WriteLog("监听定时器异常......");
            }
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            TCPSocks5Server server = null;
            if ("启动服务".Equals(btnStartServer.Text))
            {
                decimal port = nudPort.Value;
                string username = txtUsername.Text;
                string password = txtPassword.Text;
                if (string.IsNullOrWhiteSpace(username))
                {
                    WriteLog("用户名不能为空.......");
                    return;
                }
                if (string.IsNullOrWhiteSpace(username))
                {
                    WriteLog("密码不能为空.......");
                    return;
                }
                btnStartServer.Text = "退出程序";
                nudPort.ReadOnly = true;
                txtUsername.ReadOnly = true;
                txtPassword.ReadOnly = true;
                server = new TCPSocks5Server((ushort)port, username, password);
                //server.LogWatcher = Console.Out;
                server.LogW = this.WriteLog;
                server.Start();

                this.Text = this.Text + "---端口：" + port;

                string hostName = Dns.GetHostName();   //获取本机名
                WriteLog("本机名......." + hostName);
                IPHostEntry localhost = Dns.GetHostByName(hostName);    //可以获取IPv4的地址
                IPAddress localaddr = localhost.AddressList[0];
                string ipaddress = localaddr.ToString();
                WriteLog("本机IP......." + localaddr.ToString());
                string publicip = GetPublicIp();
                WriteLog("本机公网IP......." + publicip);
                txtLink.Text = string.Format("https://t.me/socks?server={0}&port={1}&user={2}&pass={3}", publicip, port, username, password);
                btnCopy.Enabled = true;
            }
            else
            {
                if (server != null) {
                    server.Stop();
                }
                Thread.Sleep(1000);
                Environment.Exit(0);
            }

        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            ClearLog();
        }

        private void btnCopy_Click(object sender, EventArgs e)
        {
            try
            {
                Clipboard.SetDataObject(txtLink.Text);
                WriteLog("复制成功......." + txtLink.Text);
            }
            catch
            {
                WriteLog("复制失败,请手动复制.......");
            }
        }

        private string GetPublicIp()
        {
            var urlList = new List<string>
            {
                "http://pv.sohu.com/cityjson?ie=utf-8",
            };
            var tempip = "";
            foreach (var a in urlList)
            {
                try
                {
                    var req = WebRequest.Create(a);
                    req.Timeout = 20000;
                    var response = req.GetResponse();
                    var resStream = response.GetResponseStream();
                    if (resStream != null)
                    {
                        var sr = new StreamReader(resStream, Encoding.UTF8);
                        var htmlinfo = sr.ReadToEnd();
                        //匹配IP的正则表达式
                        var r = new Regex("((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|[1-9])", RegexOptions.None);
                        var mc = r.Match(htmlinfo);
                        //获取匹配到的IP
                        tempip = mc.Groups[0].Value;
                        resStream.Close();
                        sr.Close();
                        response.Dispose();
                    }
                    return tempip;
                }
                catch (Exception err)
                {
                    WriteLog("当前探测URL:" + a + ",错误描述：" + err.ToString());
                }
            }
            return tempip;
        }
    }
}
